/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp;

import java.util.logging.Level;
import ssp.database.DatabaseManager;
import ssp.database.NetworkMap;
import ssp.event.ArrivalEvent;
import ssp.event.AvailabillityUpdateEvent;
import ssp.event.EventQueue;
import ssp.event.NetworkMapUpdateEvent;
import ssp.event.PathTableUpdateEvent;
import ssp.event.ServiceMapUpdateEvent;
import ssp.net.NWcomponent;
import ssp.net.NWcomponentFactory;
import ssp.net.NWcomponentManager;
import ssp.net.NWresourceFactory;
import ssp.service.FrontendServerFactory;
import ssp.service.ServiceEntryFactory;
import ssp.topology.TopologyMaker;
import ssp.utility.LoggingManager;
import ssp.utility.PropertyManager;

/**
 *
 * @author yamazaki
 * @version 0.0.1
 */
public class Simulation {
    
    final static String version = "0.0.3";
    
    public static void main(String args[]) {
        
        LoggingManager.logging(Level.INFO, "Simulator version=" + version, new Throwable());
        
        double dbInterval = PropertyManager.getValueAsDouble("AvailabillityUpdateInterval");
        LoggingManager.logging(Level.INFO, "Arrival rate: " + PropertyManager.getValueAsDouble("ArraivalRate"), new Throwable());
        if(PropertyManager.getValueAsBoolean("AlwaysUpdateDatabase")) {
            LoggingManager.logging(Level.INFO, "Database update interval: 0", new Throwable());
        } else if(dbInterval == 0.0){
            LoggingManager.logging(Level.INFO, "Database update interval: INF", new Throwable());
        } else {
            LoggingManager.logging(Level.INFO, "Database update interval: " + dbInterval, new Throwable());
        }
        
        LoggingManager.logging(Level.INFO, "The number of simulation: " + PropertyManager.getValueAsInteger("SimulationNum"), new Throwable());
        
        for(int simulationNum=0 ; simulationNum<PropertyManager.getValueAsInteger("SimulationNum") ; simulationNum++) {
            
            NWcomponentFactory.createNWcomponent(PropertyManager.getValueAsInteger("NWcomponentNum"));
            TopologyMaker.makeWSmodel(PropertyManager.getValueAsInteger("LinkNum"), PropertyManager.getValueAsDouble("LinkProb"));
            NWcomponentManager.getINSTANCE().initAllInternalPathMap();
            NWresourceFactory.allocateNWresource(PropertyManager.getValueAsInteger("NetworkRequirementNum"), PropertyManager.getValueAsInteger("NetworkRequirementRange"), PropertyManager.getValueAsDouble("NetworkRequirementMax"));
            
            FrontendServerFactory.createFrontendServer(PropertyManager.getValueAsInteger("FrontendServerNum"), PropertyManager.getValueAsDouble("FrontendServerMinCapacity"), PropertyManager.getValueAsDouble("FrontendServerMaxCapacity"));
            FrontendServerFactory.allocateFrontendServer();
            
            ServiceEntryFactory.createServiceEntry(PropertyManager.getValueAsInteger("ServiceEntryTypeNum"), PropertyManager.getValueAsInteger("ServiceEntryNumOfFrontendServer"), PropertyManager.getValueAsInteger("ServiceRequirementNum"), PropertyManager.getValueAsInteger("ServiceRequirementRange"));
            
            EventQueue eventQueue = EventQueue.getINSTANCE();
            
            eventQueue.addEvent(new NetworkMapUpdateEvent(0.0));
            eventQueue.nextEvent();
            eventQueue.addEvent(new ServiceMapUpdateEvent(0.0));
            eventQueue.nextEvent();
            if(PropertyManager.getValueAsString("Strategy").equals("agent_v1_strategy_v4")) {
                eventQueue.addEvent(new PathTableUpdateEvent(0.0));
                eventQueue.nextEvent();
            }
            eventQueue.addEvent(new AvailabillityUpdateEvent(PropertyManager.getValueAsDouble("AvailabillityUpdateInterval")));
            
            NetworkMap NWDB = DatabaseManager.getINSTANCE().getNetworkMap();
            for(NWcomponent src : NWcomponentManager.getINSTANCE().getNWcomponentList()) {
                NWDB.updateConnectionTable(0.0, src);
                NWDB.updateHopCountTable(0.0, src);
            }
            
            eventQueue.addEvent(new ArrivalEvent(1.0, PropertyManager.getValueAsInteger("ArrivalNum")));
            
            while(eventQueue.nextEvent());
            
            SimulationManager.initAll();
        }
    }
    
}
